/*     */ package com.zimbra.cs.service;
/*     */ 
/*     */ import com.zimbra.common.account.Key.AccountBy;
/*     */ import com.zimbra.common.account.Key.DomainBy;
/*     */ import com.zimbra.common.account.ZAttrProvisioning.AutoProvAuthMech;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.account.AccountServiceException;
/*     */ import com.zimbra.cs.account.AccountServiceException.AuthFailedServiceException;
/*     */ import com.zimbra.cs.account.AuthToken;
/*     */ import com.zimbra.cs.account.AuthTokenException;
/*     */ import com.zimbra.cs.account.Domain;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.account.Server;
/*     */ import com.zimbra.cs.account.ZimbraAuthToken;
/*     */ import com.zimbra.cs.account.names.NameUtil.EmailAddress;
/*     */ import com.zimbra.cs.httpclient.URLUtil;
/*     */ import com.zimbra.cs.servlet.ZimbraServlet;
/*     */ import java.io.IOException;
/*     */ import java.io.UnsupportedEncodingException;
/*     */ import java.net.URLEncoder;
/*     */ import java.util.Enumeration;
/*     */ import java.util.HashMap;
/*     */ import java.util.HashSet;
/*     */ import java.util.Map;
/*     */ import javax.servlet.ServletException;
/*     */ import javax.servlet.http.HttpServletRequest;
/*     */ import javax.servlet.http.HttpServletResponse;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class PreAuthServlet
/*     */   extends ZimbraServlet
/*     */ {
/*     */   public static final String PARAM_PREAUTH = "preauth";
/*     */   public static final String PARAM_AUTHTOKEN = "authtoken";
/*     */   public static final String PARAM_ACCOUNT = "account";
/*     */   public static final String PARAM_ADMIN = "admin";
/*     */   public static final String PARAM_ISREDIRECT = "isredirect";
/*     */   public static final String PARAM_BY = "by";
/*     */   public static final String PARAM_REDIRECT_URL = "redirectURL";
/*     */   public static final String PARAM_TIMESTAMP = "timestamp";
/*     */   public static final String PARAM_EXPIRES = "expires";
/*  67 */   private static final HashSet<String> sPreAuthParams = new HashSet();
/*     */   private static final String DEFAULT_MAIL_URL = "/zimbra";
/*     */   
/*  70 */   static { sPreAuthParams.add("preauth");
/*  71 */     sPreAuthParams.add("authtoken");
/*  72 */     sPreAuthParams.add("account");
/*  73 */     sPreAuthParams.add("admin");
/*  74 */     sPreAuthParams.add("isredirect");
/*  75 */     sPreAuthParams.add("by");
/*  76 */     sPreAuthParams.add("timestamp");
/*  77 */     sPreAuthParams.add("expires");
/*     */   }
/*     */   
/*     */   public void init() throws ServletException
/*     */   {
/*  82 */     String name = getServletName();
/*  83 */     ZimbraLog.account.info("Servlet " + name + " starting up");
/*  84 */     super.init();
/*     */   }
/*     */   
/*     */   public void destroy()
/*     */   {
/*  89 */     String name = getServletName();
/*  90 */     ZimbraLog.account.info("Servlet " + name + " shutting down");
/*  91 */     super.destroy();
/*     */   }
/*     */   
/*     */   private String getRequiredParam(HttpServletRequest req, HttpServletResponse resp, String paramName) throws ServiceException {
/*  95 */     String param = req.getParameter(paramName);
/*  96 */     if (param == null) throw ServiceException.INVALID_REQUEST("missing required param: " + paramName, null);
/*  97 */     return param;
/*     */   }
/*     */   
/*     */   private String getOptionalParam(HttpServletRequest req, String paramName, String def) {
/* 101 */     String param = req.getParameter(paramName);
/* 102 */     if (param == null) return def;
/* 103 */     return param;
/*     */   }
/*     */   
/*     */   public void doGet(HttpServletRequest req, HttpServletResponse resp)
/*     */     throws ServletException, IOException
/*     */   {
/*     */     
/*     */     try
/*     */     {
/* 112 */       Provisioning prov = Provisioning.getInstance();
/* 113 */       Server server = prov.getLocalServer();
/* 114 */       String referMode = server.getAttr("zimbraMailReferMode", "wronghost");
/*     */       
/* 116 */       boolean isRedirect = getOptionalParam(req, "isredirect", "0").equals("1");
/* 117 */       String rawAuthToken = getOptionalParam(req, "authtoken", null);
/* 118 */       AuthToken authToken = null;
/* 119 */       if (rawAuthToken != null) {
/* 120 */         authToken = AuthProvider.getAuthToken(rawAuthToken);
/* 121 */         if (authToken == null)
/* 122 */           throw new AuthTokenException("unable to get auth token from authtoken");
/* 123 */         if (authToken.isExpired())
/* 124 */           throw new AuthTokenException("auth token expired");
/* 125 */         if (!authToken.isRegistered()) {
/* 126 */           throw new AuthTokenException("authtoken is invalid");
/*     */         }
/*     */       }
/*     */       
/* 130 */       if (rawAuthToken != null) {
/* 131 */         if (!authToken.isRegistered()) {
/* 132 */           throw new AuthTokenException("authtoken is not registered");
/*     */         }
/* 134 */         if (authToken.isExpired()) {
/* 135 */           throw new AuthTokenException("authtoken is expired registered");
/*     */         }
/*     */         
/*     */ 
/* 139 */         boolean isAdmin = (authToken != null) && (AuthToken.isAnyAdmin(authToken));
/* 140 */         Account acct = prov.get(Key.AccountBy.id, authToken.getAccountId(), authToken);
/* 141 */         if ((isAdmin) || (!needReferral(acct, referMode, isRedirect)))
/*     */         {
/* 143 */           if ((authToken instanceof ZimbraAuthToken)) {
/* 144 */             ZimbraAuthToken oneTimeToken = (ZimbraAuthToken)authToken;
/* 145 */             ZimbraAuthToken newZimbraAuthToken = null;
/*     */             try {
/* 147 */               newZimbraAuthToken = oneTimeToken.clone();
/*     */             } catch (CloneNotSupportedException e) {
/* 149 */               throw new ServletException(e);
/*     */             }
/* 151 */             newZimbraAuthToken.resetTokenId();
/*     */             
/* 153 */             oneTimeToken.deRegister();
/* 154 */             authToken = newZimbraAuthToken;
/* 155 */             ZimbraLog.account.debug("Deregistered the one time preauth token and issuing new one to the user.");
/*     */           }
/*     */           
/* 158 */           setCookieAndRedirect(req, resp, authToken);
/*     */ 
/*     */         }
/*     */         else
/*     */         {
/*     */ 
/* 164 */           redirectToCorrectServer(req, resp, acct, rawAuthToken);
/*     */         }
/*     */         
/*     */       }
/*     */       else
/*     */       {
/* 170 */         String preAuth = getRequiredParam(req, resp, "preauth");
/* 171 */         String account = getRequiredParam(req, resp, "account");
/* 172 */         String accountBy = getOptionalParam(req, "by", Key.AccountBy.name.name());
/* 173 */         Key.AccountBy by = Key.AccountBy.fromString(accountBy);
/*     */         
/* 175 */         boolean admin = (getOptionalParam(req, "admin", "0").equals("1")) && (isAdminRequest(req));
/* 176 */         long timestamp = Long.parseLong(getRequiredParam(req, resp, "timestamp"));
/* 177 */         long expires = Long.parseLong(getRequiredParam(req, resp, "expires"));
/*     */         
/* 179 */         Account acct = null;
/* 180 */         acct = prov.get(by, account, authToken);
/*     */         
/* 182 */         Map<String, Object> authCtxt = new HashMap();
/* 183 */         authCtxt.put("ocip", ZimbraServlet.getOrigIp(req));
/* 184 */         authCtxt.put("remoteip", ZimbraServlet.getClientIp(req));
/* 185 */         authCtxt.put("anp", account);
/* 186 */         authCtxt.put("ua", req.getHeader("User-Agent"));
/*     */         
/* 188 */         boolean acctAutoProvisioned = false;
/* 189 */         if (acct == null)
/*     */         {
/*     */ 
/*     */ 
/* 193 */           if ((by == Key.AccountBy.name) && (!admin)) {
/*     */             try {
/* 195 */               NameUtil.EmailAddress email = new NameUtil.EmailAddress(account, false);
/* 196 */               String domainName = email.getDomain();
/* 197 */               Domain domain = domainName == null ? null : prov.get(Key.DomainBy.name, domainName);
/* 198 */               prov.preAuthAccount(domain, account, accountBy, timestamp, expires, preAuth, authCtxt);
/* 199 */               acct = prov.autoProvAccountLazy(domain, account, null, ZAttrProvisioning.AutoProvAuthMech.PREAUTH);
/*     */               
/* 201 */               if (acct != null) {
/* 202 */                 acctAutoProvisioned = true;
/*     */               }
/*     */             } catch (AccountServiceException.AuthFailedServiceException e) {
/* 205 */               ZimbraLog.account.debug("auth failed, unable to auto provisioing acct " + account, e);
/*     */             } catch (ServiceException e) {
/* 207 */               ZimbraLog.account.info("unable to auto provisioing acct " + account, e);
/*     */             }
/*     */           }
/*     */         }
/*     */         
/* 212 */         if (acct == null) {
/* 213 */           throw AccountServiceException.AuthFailedServiceException.AUTH_FAILED(account, account, "account not found");
/*     */         }
/*     */         
/* 216 */         String accountStatus = acct.getAccountStatus(prov);
/* 217 */         if (!"active".equalsIgnoreCase(accountStatus)) {
/* 218 */           if ("maintenance".equalsIgnoreCase(accountStatus)) {
/* 219 */             throw AccountServiceException.MAINTENANCE_MODE();
/*     */           }
/* 221 */           throw AccountServiceException.ACCOUNT_INACTIVE(acct.getName());
/*     */         }
/*     */         
/*     */ 
/* 225 */         if (admin) {
/* 226 */           boolean isDomainAdminAccount = acct.getBooleanAttr("zimbraIsDomainAdminAccount", false);
/* 227 */           boolean isAdminAccount = acct.getBooleanAttr("zimbraIsAdminAccount", false);
/* 228 */           boolean isDelegatedAdminAccount = acct.getBooleanAttr("zimbraIsDelegatedAdminAccount", false);
/* 229 */           boolean ok = (isDomainAdminAccount) || (isAdminAccount) || (isDelegatedAdminAccount);
/* 230 */           if (!ok) {
/* 231 */             throw ServiceException.PERM_DENIED("not an admin account");
/*     */           }
/*     */         }
/*     */         
/*     */ 
/* 236 */         if ((admin) || (!needReferral(acct, referMode, isRedirect)))
/*     */         {
/* 238 */           if (!acctAutoProvisioned) {
/* 239 */             prov.preAuthAccount(acct, account, accountBy, timestamp, expires, preAuth, admin, authCtxt);
/*     */           }
/*     */           
/*     */           AuthToken at;
/*     */           AuthToken at;
/* 244 */           if (admin) {
/* 245 */             at = expires == 0L ? AuthProvider.getAuthToken(acct, admin) : AuthProvider.getAuthToken(acct, expires, admin, null);
/*     */           } else {
/* 247 */             at = expires == 0L ? AuthProvider.getAuthToken(acct) : AuthProvider.getAuthToken(acct, expires);
/*     */           }
/* 249 */           setCookieAndRedirect(req, resp, at);
/*     */ 
/*     */         }
/*     */         else
/*     */         {
/*     */ 
/* 255 */           redirectToCorrectServer(req, resp, acct, null);
/*     */         }
/*     */       }
/*     */     } catch (ServiceException e) {
/* 259 */       resp.sendError(400, e.getMessage());
/*     */     } catch (AuthTokenException e) {
/* 261 */       resp.sendError(400, e.getMessage());
/*     */     }
/*     */   }
/*     */   
/*     */   private boolean needReferral(Account acct, String referMode, boolean isRedirect) throws ServiceException
/*     */   {
/* 267 */     if (isRedirect) {
/* 268 */       return false;
/*     */     }
/* 270 */     return ("always".equals(referMode)) || (("wronghost".equals(referMode)) && (!Provisioning.onLocalServer(acct)));
/*     */   }
/*     */   
/*     */   private void addQueryParams(HttpServletRequest req, StringBuilder sb, boolean first, boolean nonPreAuthParamsOnly)
/*     */   {
/* 275 */     Enumeration names = req.getParameterNames();
/* 276 */     while (names.hasMoreElements()) {
/* 277 */       String name = (String)names.nextElement();
/*     */       
/* 279 */       if ((!nonPreAuthParamsOnly) || (!sPreAuthParams.contains(name)))
/*     */       {
/*     */ 
/* 282 */         String[] values = req.getParameterValues(name);
/* 283 */         if (values != null) {
/* 284 */           for (String value : values) {
/* 285 */             if (first) {
/* 286 */               first = false;
/*     */             } else {
/* 288 */               sb.append('&');
/*     */             }
/*     */             try {
/* 291 */               sb.append(name).append("=").append(URLEncoder.encode(value, "utf-8"));
/*     */             }
/*     */             catch (UnsupportedEncodingException e) {
/* 294 */               sb.append(name).append("=").append(URLEncoder.encode(value));
/*     */             }
/*     */           }
/*     */         }
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static final String DEFAULT_ADMIN_URL = "/zimbraAdmin";
/*     */   
/*     */ 
/*     */ 
/*     */   private void redirectToCorrectServer(HttpServletRequest req, HttpServletResponse resp, Account acct, String token)
/*     */     throws ServiceException, IOException
/*     */   {
/* 313 */     StringBuilder sb = new StringBuilder();
/* 314 */     Provisioning prov = Provisioning.getInstance();
/* 315 */     sb.append(URLUtil.getServiceURL(prov.getServer(acct), req.getRequestURI(), true));
/* 316 */     sb.append('?').append("isredirect").append('=').append('1');
/*     */     
/* 318 */     if (token != null) {
/* 319 */       sb.append('&').append("authtoken").append('=').append(token);
/*     */       
/* 321 */       addQueryParams(req, sb, false, true);
/*     */     }
/*     */     else {
/* 324 */       addQueryParams(req, sb, false, false);
/*     */     }
/*     */     
/* 327 */     resp.sendRedirect(sb.toString());
/*     */   }
/*     */   
/*     */ 
/*     */   private void setCookieAndRedirect(HttpServletRequest req, HttpServletResponse resp, AuthToken authToken)
/*     */     throws IOException, ServiceException
/*     */   {
/* 334 */     boolean isAdmin = AuthToken.isAnyAdmin(authToken);
/* 335 */     boolean secureCookie = req.getScheme().equals("https");
/* 336 */     authToken.encode(resp, isAdmin, secureCookie);
/*     */     
/* 338 */     String redirectURL = getOptionalParam(req, "redirectURL", null);
/* 339 */     if (redirectURL != null) {
/* 340 */       resp.sendRedirect(redirectURL);
/*     */     } else {
/* 342 */       StringBuilder sb = new StringBuilder();
/* 343 */       addQueryParams(req, sb, true, true);
/* 344 */       Provisioning prov = Provisioning.getInstance();
/* 345 */       Server server = prov.getServer(authToken.getAccount());
/*     */       String redirectUrl;
/*     */       String redirectUrl;
/* 348 */       if (isAdmin) {
/* 349 */         redirectUrl = server.getAttr("zimbraAdminURL", "/zimbraAdmin");
/*     */       } else {
/* 351 */         redirectUrl = server.getAttr("zimbraMailURL", "/zimbra");
/*     */         
/* 353 */         if (redirectUrl.charAt(redirectUrl.length() - 1) == '/') {
/* 354 */           redirectUrl = redirectUrl + "mail";
/*     */         } else {
/* 356 */           redirectUrl = redirectUrl + "/mail";
/*     */         }
/*     */       }
/* 359 */       if (sb.length() > 0) {
/* 360 */         resp.sendRedirect(redirectUrl + "?" + sb.toString());
/*     */       } else {
/* 362 */         resp.sendRedirect(redirectUrl);
/*     */       }
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/service/PreAuthServlet.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */